package com.niguang.work.labour.common.interceptor;


import com.niguang.work.labour.common.constant.ResultCode;
import com.niguang.work.labour.common.pojo.Result;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MultipartException;

import java.rmi.RemoteException;


@Slf4j
@RestControllerAdvice
public class WebControllerAdvice {

    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(BindException e) {
        log.error("接口出错!", e);
        return Result.build(ResultCode.METHOD_NOT_ALLOWED, e.getFieldError().getDefaultMessage());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(HttpRequestMethodNotSupportedException e) {
        log.error("不支持的HTTP请求方法!", e);
        return Result.build(ResultCode.METHOD_NOT_ALLOWED, "此接口不支持(" + e.getMethod() + ")方法请求!", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(HttpMediaTypeNotSupportedException e) {
        log.error("不支持的HTTP类型请求!", e.getSupportedMediaTypes());
        return Result.build(ResultCode.METHOD_NOT_ALLOWED, "此接口不支持(" + e.getContentType() + ")类型请求!", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(HttpMessageNotReadableException e) {
        log.error("读取不到Json数据，Json对象为空!", e);
        return Result.build(ResultCode.PARAM_ERROR, "读取不到Json数据，Json对象为空!", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(MethodArgumentNotValidException e) {
        log.error("数据检验失败!", e);
        return Result.build(ResultCode.PARAM_ERROR, e.getBindingResult().getFieldError().getDefaultMessage());
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(MissingServletRequestParameterException e) {
        log.error("参数异常!", e);
        return Result.build(ResultCode.PARAM_ERROR, "(" + e.getParameterName() + ")参数是必须的", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(MethodArgumentTypeMismatchException e) {
        log.error("参数类型不匹配!", e);
        return Result.build(ResultCode.PARAM_ERROR, "(" + e.getName() + ")参数类型不匹配", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(DuplicateKeyException e) {
        log.error("主键重复!", e);
        return Result.build(ResultCode.CONFLICT, "主键重复,请勿重复添加!", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(RemoteException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(RemoteException e) {
        log.error("调用远程服务器失败!", e);
        return Result.build(ResultCode.SERVICE_UNAVAILABLE, "调用远程服务器失败!", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(NullPointerException e) {
        log.error("参数不能为空!", e);
        return Result.build(ResultCode.PARAM_ERROR, "参数" + e.getMessage() + "不能为空!", ResultCode.FAILED.getDesc());
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(Exception e) {
        log.error("程序异常", e);
        return Result.build(ResultCode.PARAM_ERROR, e.getMessage(), ResultCode.FAILED.getDesc());
    }






    /*@ExceptionHandler(IllegalStateException.class)
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public Result<Object> exception(IllegalStateException e) {
        if (e.getCause() instanceof FileUploadBase.SizeLimitExceededException) {
            log.error("超过文件大小限制!", e);
            return new Result<>(Result.SERVER_ERROR, "", "上传失败!文件大小超过6M!");
        }
        log.error("IllegalStateException!", e);
        return new Result<>(Result.SERVER_ERROR, e.getMessage(), e.toString());
    }
*/

    @ExceptionHandler(MultipartException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(MultipartException e) {
        log.error("超过文件大小限制!", e);
        return Result.build(ResultCode.INSUFFICIENT_SPACE_ON_RESOURCE, "上传失败!文件大小超过20M!");
    }


    @ExceptionHandler(ExpiredJwtException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(ExpiredJwtException e) {
        log.error("令牌超时,请重新登录!", e);
        return Result.build(ResultCode.UNAUTHORIZED, "令牌超时,请重新登录!");
    }


    @ExceptionHandler(SignatureException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(SignatureException e) {
        log.error("令牌解析出错!", e);
        return Result.build(ResultCode.UNAUTHORIZED, "令牌解析出错,请重新登录!");
    }

    @ExceptionHandler(MalformedJwtException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(MalformedJwtException e) {
        log.error("令牌无效!", e);
        return Result.build(ResultCode.UNAUTHORIZED, "令牌无效,请重新登录!");
    }

    @ExceptionHandler(UnsupportedJwtException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result exception(UnsupportedJwtException e) {
        log.error("不支持的令牌!", e);
        return Result.build(ResultCode.UNAUTHORIZED, "不支持的令牌,请重新登录!");
    }

}
